unit AgenteGrid;

interface
uses
  Agente, Classes, Acao, Estado, EstadoGrid, Ambiente;

type
  TAgenteGrid = class (TAgente)
    private
      FListaDeAcao  : TList;

      FMemoria      : array of array of TPropriedadeGrid;
      FXMemoria,
      FYMemoria     : Integer;
    public
      function Percebe (E : TAmbiente)        : TEstado; override;
      constructor Create (XMemoria, YMemoria : Integer);
      destructor Destroy; override;

      function NumeroDeAcoes  : Integer;

      function Recompensa(s : TEstado)   : double;

      function EscolheAcao    : TAcao; override;

      procedure LimpaMemoria;

  end;

implementation
uses
  AcaoGrid, SysUtils;

{ TAgenteGrid }

function TAgenteGrid.EscolheAcao: TAcao;
begin

  Result := TAcao (FListaDeAcao[Random(FListaDeAcao.Count)]);

end;

constructor TAgenteGrid.Create (XMemoria, YMemoria : Integer);
var
  i, j : Integer;
  a : TAcaoGrid;
begin
  FListaDeAcao := TList.Create;

  FXMemoria := XMemoria;
  FYMemoria := YMemoria;

  for i := 0 to TAcaoGrid.NumeroDeAcoes-1 do
    begin
      a := TAcaoGrid.Create(i);
      FListaDeAcao.Add(a);
    end;

   SetLength(FMemoria, YMemoria, XMemoria);

   for i :=0 to YMemoria-1 do
    for j :=0 to XMemoria-1 do
      FMemoria[i][j] := pgDesconhecido;

end;

destructor TAgenteGrid.Destroy;
var
  i : Integer;

  a : TAcaoGrid;
begin

  for i := 0 to FListaDeAcao.Count-1 do
    begin
      a := TAcaoGrid(FListaDeAcao[i]);

      FreeAndNil(a);

    end;

  FreeAndNil(FListaDeAcao);

  inherited;
end;

function TAgenteGrid.NumeroDeAcoes: Integer;
begin
  Result := TAcaoGrid.NumeroDeAcoes;
end;

function TAgenteGrid.Percebe(E: TAmbiente): TEstado;
var
  sgrid : TEstadoGrid;
begin
  Result :=  E.EstadoAgente;

  sgrid := TEstadoGrid(E.EstadoAgente);

  FMemoria[sgrid.Y, sgrid.X] := sgrid.Propriedade;

  sgrid.Descricao := TEstadoGrid.GridPropertyToString(FMemoria[sgrid.Y, sgrid.X]);

  if (sgrid.Y > 0) then
    sgrid.Descricao := sgrid.Descricao + TEstadoGrid.GridPropertyToString(FMemoria[sgrid.Y-1, sgrid.X])
  else
    sgrid.Descricao := sgrid.Descricao + TEstadoGrid.GridPropertyToString(pgMuro);

  if (sgrid.X > 0) then
    sgrid.Descricao := sgrid.Descricao + TEstadoGrid.GridPropertyToString(FMemoria[sgrid.Y, sgrid.X-1])
  else
    sgrid.Descricao := sgrid.Descricao + TEstadoGrid.GridPropertyToString(pgMuro);

  if (sgrid.Y < FYMemoria-1) then
    sgrid.Descricao := sgrid.Descricao + TEstadoGrid.GridPropertyToString(FMemoria[sgrid.Y+1, sgrid.X])
  else
    sgrid.Descricao := sgrid.Descricao + TEstadoGrid.GridPropertyToString(pgMuro);

  if (sgrid.X < FXMemoria-1) then
    sgrid.Descricao := sgrid.Descricao + TEstadoGrid.GridPropertyToString(FMemoria[sgrid.Y, sgrid.X+1])
  else
    sgrid.Descricao := sgrid.Descricao + TEstadoGrid.GridPropertyToString(pgMuro);

end;

procedure TAgenteGrid.LimpaMemoria;
var
  i, j : Integer;
begin
  for i :=0 to FYMemoria-1 do
    for j :=0 to FXMemoria-1 do
      FMemoria[i][j] := pgDesconhecido;
end;

function TAgenteGrid.Recompensa (s : TEstado): double;
var
  sgrid : TEstadoGrid;
begin

  sgrid := TEstadoGrid(s);

  if (FMemoria[sgrid.Y][sgrid.X] = pgDesconhecido) then
    Result := 50
  else
    Result := 0;
end;

end.
